/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * NoteSelectorPanel.java
 *
 * Created on 31/08/2009, 11:31:43 AM
 */

package net.animats.music.app;

import java.awt.*;
import net.animats.music.*;
import java.util.List;
import java.util.ArrayList;

/**
 *
 * @author stuart
 */
public class NoteSelectorPanel extends javax.swing.JPanel {

    // THESE TWO ARRAYS ARE THE INDEXES INTO THE Notes ARRAY. FOR EXAMPLE, THE SECOND
    // BLACK KEY FROM THE LEFT CORRESPONDS TO THE NOTE AT INDEX 3.
    // -1 INDICATES THAT THERE IS NO BLACK KEY IN THAT POSITION
    private static int[] blackKeys = { 1, 3, -1, 6, 8, 10, -1, 13, 15, -1, 18, 20, 22 };
    private static int[] whiteKeys = { 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 17, 19, 21, 23 };

    private static Note[] noteMapping = new Note[27];

    // CREATE AN ARRAY THAT MAPS NOTES TO THE KEYS ON THE SELECTOR
    static {
        for (int index = 0, counter = -9; counter < 15; counter++, index++) {
            noteMapping[index] = Note.getNote(counter);
        }
    }

    // SHOULD THE KEYS BE HIGHLIGHTED (ARE THEY SELECTED)
    private boolean[] blackSelected = { false, false, false, false, false, false, false, false, false, false, false, false, false };
    private boolean[] whiteSelected = { false, false, false, false, false, false, false, false, false, false, false, false, false, false };

    private NoteSet notes = new NoteSet();

    private List<NoteSelectorListener> listeners = new ArrayList<NoteSelectorListener>();

    public void addListener(NoteSelectorListener _listener) {
        listeners.add(_listener);
    }

    private void callListeners() {
        for (NoteSelectorListener currentListener : listeners) {
            currentListener.noteSetChanged(notes);
        }
    }
    
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.BLACK);
        for (int index = 0; index < 14; index++) {
            g.drawRect(30 * index, 0, 30, 120);
            if (whiteSelected[index] == true) {
                g.setColor(Color.GRAY);
                g.fillRect((30 * index) + 1, 1, 29, 119);
                g.setColor(Color.BLACK);
            }
        }

        for (int index = 0; index < 13; index++) {
            if (index != 2 &&
                index != 6 &&
                index != 9) {
                g.fillRect(20 + (30 * index), 0, 20, 70);
                if (blackSelected[index] == true) {
                    g.setColor(Color.GRAY);
                    g.fillRect(21 + (30 * index), 1, 18, 68);
                    g.setColor(Color.BLACK);
                }
            }
        }
    }

    /** Creates new form NoteSelectorPanel */
    public NoteSelectorPanel() {
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        setMaximumSize(new java.awt.Dimension(421, 121));
        setMinimumSize(new java.awt.Dimension(421, 121));
        setPreferredSize(new java.awt.Dimension(421, 121));
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                formMouseClicked(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 421, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 121, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents

    public NoteSet getNoteSet() {
        return notes;
    }
    
    private void formMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_formMouseClicked
        int left, right;

        // CHECK IF THE CLICK FALLS IN A BLACK KEY FIRST
         if (evt.getY() < 70) {
            // CLICKED HIGHER THAN THE BOTTOM OF THE BLACK KEYS,
            // SO FAR SO GOOD
            for (int key = 0; key < 13; key++) {
                // CALCULATE THE LEFT AND RIGHT LIMITS FOR EACH OF
                // THE THIRTEEN BLACK KEY SPACES
                // (NOTE, SOME OF THE BLACK KEY SPACES MAY NOT HAVE
                // AN ACTUAL KEY THERE...
                left = 20 + (30 * key);
                right = 40 + (30 * key);
                if (evt.getX() > left && evt.getX() < right) {
                    // CLICK IS IN THIS KEY
                    if (blackKeys[key] ==  -1) {
                        // THERE IS NO BLACK KEY IN THIS SPACE, MUST
                        // HAVE CLICKED ONE OF THE WHITE KEYS
                        break;
                    } else {
                        // TOGGLE THE SELECTION STATUS FOR THIS KEY
                        blackSelected[key] = !blackSelected[key];
                        if (blackSelected[key]) {
                            notes.addNote(noteMapping[blackKeys[key]]);
                        } else {
                            notes.removeNote(noteMapping[blackKeys[key]]);
                        }
                        repaint();
                        callListeners();
                        return;
                    }
                }
            }
        }

        // NO BLACK KEY WAS CLICKED, NOW CHECK ALL THE WHITE KEYS
        for (int key = 0; key < 14; key++) {
             // CALCULATE THE LEFT AND RIGHT LIMITS FOR EACH OF
             // THE FOURTEEN WHITE KEY SPACES
             left = (30 * key);
             right = 30 + (30 * key);
             if (evt.getX() > left && evt.getX() < right) {
                    // TOGGLE THE SELECTION STATUS FOR THIS KEY
                    whiteSelected[key] = !whiteSelected[key];
                    if (whiteSelected[key]) {
                        notes.addNote(noteMapping[whiteKeys[key]]);
                    } else {
                        notes.removeNote(noteMapping[whiteKeys[key]]);
                    }
                    repaint();
                    callListeners();
                    return;
             }
        }

        // HMMM.. SHOULDN'T EVER GET TO HERE
    }//GEN-LAST:event_formMouseClicked


    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables

}
